#ifndef WXSEVENTS_H
#define WXSEVENTS_H

#include <wx/arrstr.h>
#include <tinyxml.h>
#include <wx/arrstr.h>

#include "wxscodercontext.h"

// Forward declarations
class wxsItem;


struct wxsEventDesc {
  enum EntryType {
    Id,                     ///< \brief Event using one identifier
    IdRange,                ///< \brief Event using range of identifiers
    NoId,                   ///< \brief Event without id (can be used for root element only)
    Category,               ///< \brief Not really entry, but starts new category
    EndOfList               ///< \brief End of list of events
  };

  EntryType ET;               ///< \brief Type of entry
  wxString Entry;             ///< \brief Name of entry inside event table
  wxString Type;              ///< \brief Macro of event type used inside event table
  wxString ArgType;           ///< \brief Name of type of argument passed to event-processing function
  wxString NewFuncNameBase;   ///< \brief Base for new function name, it will be created as "On" + VarName + NewFuncName
};


#define WXS_EV_BEGIN(name)                                          \
  static wxsEventDesc name[] = {


#define WXS_EV(entry,type,arg,funcbase)                             \
  { wxsEventDesc::NoId, _T(#entry), _T(#type), _T(#arg), _T(#funcbase) } ,


#define WXS_EVI(entry,type,arg,funcbase)                            \
  { wxsEventDesc::Id, _T(#entry), _T(#type), _T(#arg), _T(#funcbase) } ,


#define WXS_EV2I(entry,type,arg,funcbase)                            \
  { wxsEventDesc::IdRange, _T(#entry), _T(#type), _T(#arg), _T(#funcbase) } ,


#define WXS_EV_CATEGORY(name)                                       \
  { wxsEventDesc::Category, name, _T(""), _T(""), _T("") },


#define WXS_EV_END()                                                \
  { wxsEventDesc::EndOfList, _T(""), _T(""), _T(""), _T("") } };


#define WXS_EV_PAINT()                                                                  \
  WXS_EV_CATEGORY(_T("Paint events"))                                                  \
  WXS_EV(EVT_PAINT,wxEVT_PAINT,wxPaintEvent,Paint)                                    \
  WXS_EV(EVT_ERASE_BACKGROUND,wxEVT_ERASE_BACKGROUND,wxEraseEvent,EraseBackground)    \


#define WXS_EV_KEYBOARD()                                                               \
  WXS_EV_CATEGORY(_T("Keyboard events"))                                               \
  WXS_EV(EVT_KEY_DOWN,wxEVT_KEY_DOWN,wxKeyEvent,KeyDown)                              \
  WXS_EV(EVT_KEY_UP,wxEVT_KEY_UP,wxKeyEvent,KeyUp)                                    \
  WXS_EV(EVT_CHAR,wxEVT_CHAR,wxKeyEvent,Char)                                         \
  WXS_EV(EVT_SET_FOCUS,wxEVT_SET_FOCUS,wxFocusEvent,SetFocus)                         \
  WXS_EV(EVT_KILL_FOCUS,wxEVT_KILL_FOCUS,wxFocusEvent,KillFocus)

#define WXS_EV_MOUSE()                                                                  \
  WXS_EV_CATEGORY(_T("Mouse events"))                                                 \
  WXS_EV(EVT_LEFT_DOWN,wxEVT_LEFT_DOWN,wxMouseEvent,LeftDown)                         \
  WXS_EV(EVT_LEFT_UP,wxEVT_LEFT_UP,wxMouseEvent,LeftUp)                               \
  WXS_EV(EVT_LEFT_DCLICK,wxEVT_LEFT_DCLICK,wxMouseEvent,LeftDClick)                   \
  WXS_EV(EVT_MIDDLE_DOWN,wxEVT_MIDDLE_DOWN,wxMouseEvent,MiddleDown)                   \
  WXS_EV(EVT_MIDDLE_UP,wxEVT_MIDDLE_UP,wxMouseEvent,MiddleUp)                         \
  WXS_EV(EVT_MIDDLE_DCLICK,wxEVT_MIDDLE_DCLICK,wxMouseEvent,MiddleDClick)             \
  WXS_EV(EVT_RIGHT_DOWN,wxEVT_RIGHT_DOWN,wxMouseEvent,RightDown)                      \
  WXS_EV(EVT_RIGHT_UP,wxEVT_RIGHT_UP,wxMouseEvent,RightUp)                            \
  WXS_EV(EVT_RIGHT_DCLICK,wxEVT_RIGHT_DCLICK,wxMouseEvent,RightDClick)                \
  WXS_EV(EVT_MOTION,wxEVT_MOTION,wxMouseEvent,MouseMove)                              \
  WXS_EV(EVT_ENTER_WINDOW,wxEVT_ENTER_WINDOW,wxMouseEvent,MouseEnter)                 \
  WXS_EV(EVT_LEAVE_WINDOW,wxEVT_LEAVE_WINDOW,wxMouseEvent,MouseLeave)                 \
  WXS_EV(EVT_MOUSEWHEEL,wxEVT_MOUSEWHEEL,wxMouseEvent,MouseWheel)                     \
  WXS_EV(EVT_SET_CURSOR,wxEVT_SET_CURSOR,wxSetCursorEvent,SetCursor)                  \



#define WXS_EV_SIZE()                                                                   \
  WXS_EV(EVT_SIZE,wxEVT_SIZE,wxSizeEvent,Resize)



#define WXS_EV_DEFAULTS()                                                               \
  WXS_EV_PAINT()                                                                      \
  WXS_EV_KEYBOARD()                                                                   \
  WXS_EV_MOUSE()                                                                      \
  WXS_EV_SIZE()


class wxsEvents {
  public:


    wxsEvents( const wxsEventDesc* Events, wxsItem* Item );


    inline int GetCount() { return m_Count; }


    inline const wxsEventDesc* GetDesc( int Index ) { return &m_EventArray[Index]; }


    inline const wxString& GetHandler( int Index ) { return m_Functions[Index]; }


    inline void SetHandler( int Index, const wxString& Name ) { m_Functions[Index] = Name; }


    void GenerateBindingCode( wxsCoderContext* Context, const wxString& IdString, const wxString& VarNameString );


    void XmlLoadFunctions( TiXmlElement* Element );


    void XmlSaveFunctions( TiXmlElement* Element );

  private:

    wxsItem* m_Item;                      ///< Item whose events are managed
    const wxsEventDesc* m_EventArray;     ///< Array of events fetched from item
    wxArrayString m_Functions;            ///< Array of function names used for each entry item
    int m_Count;                          ///< Number of events
};

#endif
